{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "GPU1 Memory: 11172MB\n"
     ]
    }
   ],
   "source": [
    "from pynvml import *\n",
    "\n",
    "nvmlInit()\n",
    "vram = nvmlDeviceGetMemoryInfo(nvmlDeviceGetHandleByIndex(1)).free/1024.**2\n",
    "print('GPU1 Memory: %dMB' % vram)\n",
    "if vram < 8000:\n",
    "    raise Exception('GPU Memory too low')\n",
    "nvmlShutdown()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import cv2\n",
    "import h5py\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from IPython.display import *\n",
    "from collections import Counter\n",
    "import seaborn as sns\n",
    "from tqdm import tqdm\n",
    "import pandas as pd\n",
    "import re\n",
    "import time\n",
    "import random\n",
    "\n",
    "from keras.layers import *\n",
    "from keras.models import *\n",
    "from keras.optimizers import *\n",
    "from keras.regularizers import l2\n",
    "from keras.utils.vis_utils import model_to_dot\n",
    "import keras.backend as K\n",
    "from make_parallel import make_parallel\n",
    "\n",
    "%matplotlib inline\n",
    "%config InlineBackend.figure_format = 'retina'\n",
    "IMAGE_DIR = 'image_contest_level_2'\n",
    "\n",
    "DESCRIPTION = '346_split2_3'\n",
    "MODEL_NAME = 'model_%s_best.h5' % DESCRIPTION"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 载入基本数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "df = pd.read_csv('image_contest_level_2/labels.txt', sep=' ', header=None)\n",
    "characters = u'0123456789()+-*/=君不见黄河之水天上来奔流到海复回烟锁池塘柳深圳铁板烧; '\n",
    "\n",
    "labels_len = np.array(map(lambda x:len(x.decode('utf-8')), df[0]))\n",
    "n_len = 51\n",
    "n, width, height, n_class, channels = 100000, 900, 81, len(characters), 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def decode(out):\n",
    "    return ''.join([characters[x] for x in out if x < n_class-1 and x > -1])\n",
    "\n",
    "def disp2(img):\n",
    "    cv2.imwrite('a.png', img)\n",
    "    return display(Image('a.png'))\n",
    "\n",
    "def disp(img, txt=None, first=False):\n",
    "    global index\n",
    "    if first:\n",
    "        index = 1\n",
    "        plt.figure(figsize=(16, 9))\n",
    "    else:\n",
    "        index += 1\n",
    "    plt.subplot(4, 1, index)\n",
    "    if len(img.shape) == 2:\n",
    "        plt.imshow(img, cmap='gray')\n",
    "    else:\n",
    "        plt.imshow(img[:,:,::-1])\n",
    "    if txt:\n",
    "        plt.title(txt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 构建模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[None, 112, 10, 128] 112 1280\n"
     ]
    }
   ],
   "source": [
    "def ctc_lambda_func(args):\n",
    "    y_pred, labels, input_length, label_length = args\n",
    "    y_pred = y_pred[:, 2:, :]\n",
    "    return K.ctc_batch_cost(labels, y_pred, input_length, label_length)\n",
    "\n",
    "rnn_size = 128\n",
    "l2_rate = 1e-5\n",
    "\n",
    "input_tensor = Input((width, height, 3))\n",
    "x = input_tensor\n",
    "for i, n_cnn in enumerate([3, 4, 6]):\n",
    "    for j in range(n_cnn):\n",
    "        x = Conv2D(32*2**i, (3, 3), padding='same', kernel_initializer='he_uniform', \n",
    "                   kernel_regularizer=l2(l2_rate))(x)\n",
    "        x = BatchNormalization(gamma_regularizer=l2(l2_rate), beta_regularizer=l2(l2_rate))(x)\n",
    "        x = Activation('relu')(x)\n",
    "    x = MaxPooling2D((2, 2))(x)\n",
    "\n",
    "# x = AveragePooling2D((1, 2))(x)\n",
    "cnn_model = Model(input_tensor, x, name='cnn')\n",
    "\n",
    "input_tensor = Input((width, height, 3))\n",
    "x = cnn_model(input_tensor)\n",
    "\n",
    "conv_shape = x.get_shape().as_list()\n",
    "rnn_length = conv_shape[1]\n",
    "rnn_dimen = conv_shape[3]*conv_shape[2]\n",
    "\n",
    "print conv_shape, rnn_length, rnn_dimen\n",
    "\n",
    "x = Reshape(target_shape=(rnn_length, rnn_dimen))(x)\n",
    "rnn_length -= 2\n",
    "rnn_imp = 0\n",
    "\n",
    "x = Dense(rnn_size, kernel_initializer='he_uniform', kernel_regularizer=l2(l2_rate), bias_regularizer=l2(l2_rate))(x)\n",
    "x = BatchNormalization(gamma_regularizer=l2(l2_rate), beta_regularizer=l2(l2_rate))(x)\n",
    "x = Activation('relu')(x)\n",
    "# x = Dropout(0.2)(x)\n",
    "\n",
    "gru_1 = GRU(rnn_size, implementation=rnn_imp, return_sequences=True, name='gru1')(x)\n",
    "gru_1b = GRU(rnn_size, implementation=rnn_imp, return_sequences=True, go_backwards=True, name='gru1_b')(x)\n",
    "gru1_merged = add([gru_1, gru_1b])\n",
    "\n",
    "gru_2 = GRU(rnn_size, implementation=rnn_imp, return_sequences=True, name='gru2')(gru1_merged)\n",
    "gru_2b = GRU(rnn_size, implementation=rnn_imp, return_sequences=True, go_backwards=True, name='gru2_b')(gru1_merged)\n",
    "x = concatenate([gru_2, gru_2b])\n",
    "\n",
    "# x = Dropout(0.2)(x)\n",
    "x = Dense(n_class, activation='softmax', kernel_regularizer=l2(l2_rate), bias_regularizer=l2(l2_rate))(x)\n",
    "rnn_out = x\n",
    "base_model = Model(input_tensor, x)\n",
    "\n",
    "base_model2 = make_parallel(base_model, 4)\n",
    "\n",
    "labels = Input(name='the_labels', shape=[n_len], dtype='float32')\n",
    "input_length = Input(name='input_length', shape=(1,), dtype='int64')\n",
    "label_length = Input(name='label_length', shape=(1,), dtype='int64')\n",
    "loss_out = Lambda(ctc_lambda_func, name='ctc')([base_model2.output, labels, input_length, label_length])\n",
    "\n",
    "model = Model(inputs=(input_tensor, labels, input_length, label_length), outputs=loss_out)\n",
    "model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer='adam')\n",
    "model.save('test.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "____________________________________________________________________________________________________\n",
      "Layer (type)                     Output Shape          Param #     Connected to                     \n",
      "====================================================================================================\n",
      "input_2 (InputLayer)             (None, 900, 81, 3)    0                                            \n",
      "____________________________________________________________________________________________________\n",
      "cnn (Model)                      (None, 112, 10, 128)  964928      input_2[0][0]                    \n",
      "____________________________________________________________________________________________________\n",
      "reshape_1 (Reshape)              (None, 112, 1280)     0           cnn[1][0]                        \n",
      "____________________________________________________________________________________________________\n",
      "dense_1 (Dense)                  (None, 112, 128)      163968      reshape_1[0][0]                  \n",
      "____________________________________________________________________________________________________\n",
      "batch_normalization_14 (BatchNor (None, 112, 128)      512         dense_1[0][0]                    \n",
      "____________________________________________________________________________________________________\n",
      "activation_14 (Activation)       (None, 112, 128)      0           batch_normalization_14[0][0]     \n",
      "____________________________________________________________________________________________________\n",
      "gru1 (GRU)                       (None, 112, 128)      98688       activation_14[0][0]              \n",
      "____________________________________________________________________________________________________\n",
      "gru1_b (GRU)                     (None, 112, 128)      98688       activation_14[0][0]              \n",
      "____________________________________________________________________________________________________\n",
      "add_1 (Add)                      (None, 112, 128)      0           gru1[0][0]                       \n",
      "                                                                   gru1_b[0][0]                     \n",
      "____________________________________________________________________________________________________\n",
      "gru2 (GRU)                       (None, 112, 128)      98688       add_1[0][0]                      \n",
      "____________________________________________________________________________________________________\n",
      "gru2_b (GRU)                     (None, 112, 128)      98688       add_1[0][0]                      \n",
      "____________________________________________________________________________________________________\n",
      "concatenate_1 (Concatenate)      (None, 112, 256)      0           gru2[0][0]                       \n",
      "                                                                   gru2_b[0][0]                     \n",
      "____________________________________________________________________________________________________\n",
      "dense_2 (Dense)                  (None, 112, 45)       11565       concatenate_1[0][0]              \n",
      "====================================================================================================\n",
      "Total params: 1,535,725\n",
      "Trainable params: 1,533,229\n",
      "Non-trainable params: 2,496\n",
      "____________________________________________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "base_model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg height=\"885pt\" viewBox=\"0.00 0.00 524.00 885.00\" width=\"524pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 881)\">\n",
       "<title>G</title>\n",
       "<polygon fill=\"white\" points=\"-4,4 -4,-881 520,-881 520,4 -4,4\" stroke=\"none\"/>\n",
       "<!-- 140317144009872 -->\n",
       "<g class=\"node\" id=\"node1\"><title>140317144009872</title>\n",
       "<polygon fill=\"none\" points=\"105,-830.5 105,-876.5 403,-876.5 403,-830.5 105,-830.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"167.5\" y=\"-849.8\">input_2: InputLayer</text>\n",
       "<polyline fill=\"none\" points=\"230,-830.5 230,-876.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"257.5\" y=\"-861.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"230,-853.5 285,-853.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"257.5\" y=\"-838.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"285,-830.5 285,-876.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"344\" y=\"-861.3\">(None, 900, 81, 3)</text>\n",
       "<polyline fill=\"none\" points=\"285,-853.5 403,-853.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"344\" y=\"-838.3\">(None, 900, 81, 3)</text>\n",
       "</g>\n",
       "<!-- 140317124338768 -->\n",
       "<g class=\"node\" id=\"node2\"><title>140317124338768</title>\n",
       "<polygon fill=\"none\" points=\"121,-747.5 121,-793.5 387,-793.5 387,-747.5 121,-747.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"161\" y=\"-766.8\">cnn: Model</text>\n",
       "<polyline fill=\"none\" points=\"201,-747.5 201,-793.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"228.5\" y=\"-778.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"201,-770.5 256,-770.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"228.5\" y=\"-755.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"256,-747.5 256,-793.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"321.5\" y=\"-778.3\">(None, 900, 81, 3)</text>\n",
       "<polyline fill=\"none\" points=\"256,-770.5 387,-770.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"321.5\" y=\"-755.3\">(None, 112, 10, 128)</text>\n",
       "</g>\n",
       "<!-- 140317144009872&#45;&gt;140317124338768 -->\n",
       "<g class=\"edge\" id=\"edge1\"><title>140317144009872-&gt;140317124338768</title>\n",
       "<path d=\"M254,-830.366C254,-822.152 254,-812.658 254,-803.725\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"257.5,-803.607 254,-793.607 250.5,-803.607 257.5,-803.607\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317124221136 -->\n",
       "<g class=\"node\" id=\"node3\"><title>140317124221136</title>\n",
       "<polygon fill=\"none\" points=\"98.5,-664.5 98.5,-710.5 409.5,-710.5 409.5,-664.5 98.5,-664.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"161\" y=\"-683.8\">reshape_1: Reshape</text>\n",
       "<polyline fill=\"none\" points=\"223.5,-664.5 223.5,-710.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"251\" y=\"-695.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"223.5,-687.5 278.5,-687.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"251\" y=\"-672.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"278.5,-664.5 278.5,-710.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"344\" y=\"-695.3\">(None, 112, 10, 128)</text>\n",
       "<polyline fill=\"none\" points=\"278.5,-687.5 409.5,-687.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"344\" y=\"-672.3\">(None, 112, 1280)</text>\n",
       "</g>\n",
       "<!-- 140317124338768&#45;&gt;140317124221136 -->\n",
       "<g class=\"edge\" id=\"edge2\"><title>140317124338768-&gt;140317124221136</title>\n",
       "<path d=\"M254,-747.366C254,-739.152 254,-729.658 254,-720.725\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"257.5,-720.607 254,-710.607 250.5,-720.607 257.5,-720.607\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317143074704 -->\n",
       "<g class=\"node\" id=\"node4\"><title>140317143074704</title>\n",
       "<polygon fill=\"none\" points=\"117,-581.5 117,-627.5 391,-627.5 391,-581.5 117,-581.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"168\" y=\"-600.8\">dense_1: Dense</text>\n",
       "<polyline fill=\"none\" points=\"219,-581.5 219,-627.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"246.5\" y=\"-612.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"219,-604.5 274,-604.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"246.5\" y=\"-589.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"274,-581.5 274,-627.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"332.5\" y=\"-612.3\">(None, 112, 1280)</text>\n",
       "<polyline fill=\"none\" points=\"274,-604.5 391,-604.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"332.5\" y=\"-589.3\">(None, 112, 128)</text>\n",
       "</g>\n",
       "<!-- 140317124221136&#45;&gt;140317143074704 -->\n",
       "<g class=\"edge\" id=\"edge3\"><title>140317124221136-&gt;140317143074704</title>\n",
       "<path d=\"M254,-664.366C254,-656.152 254,-646.658 254,-637.725\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"257.5,-637.607 254,-627.607 250.5,-637.607 257.5,-637.607\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317137970576 -->\n",
       "<g class=\"node\" id=\"node5\"><title>140317137970576</title>\n",
       "<polygon fill=\"none\" points=\"38.5,-498.5 38.5,-544.5 469.5,-544.5 469.5,-498.5 38.5,-498.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"171.5\" y=\"-517.8\">batch_normalization_14: BatchNormalization</text>\n",
       "<polyline fill=\"none\" points=\"304.5,-498.5 304.5,-544.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"332\" y=\"-529.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"304.5,-521.5 359.5,-521.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"332\" y=\"-506.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"359.5,-498.5 359.5,-544.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"414.5\" y=\"-529.3\">(None, 112, 128)</text>\n",
       "<polyline fill=\"none\" points=\"359.5,-521.5 469.5,-521.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"414.5\" y=\"-506.3\">(None, 112, 128)</text>\n",
       "</g>\n",
       "<!-- 140317143074704&#45;&gt;140317137970576 -->\n",
       "<g class=\"edge\" id=\"edge4\"><title>140317143074704-&gt;140317137970576</title>\n",
       "<path d=\"M254,-581.366C254,-573.152 254,-563.658 254,-554.725\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"257.5,-554.607 254,-544.607 250.5,-554.607 257.5,-554.607\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317138867152 -->\n",
       "<g class=\"node\" id=\"node6\"><title>140317138867152</title>\n",
       "<polygon fill=\"none\" points=\"94,-415.5 94,-461.5 414,-461.5 414,-415.5 94,-415.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"171.5\" y=\"-434.8\">activation_14: Activation</text>\n",
       "<polyline fill=\"none\" points=\"249,-415.5 249,-461.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"276.5\" y=\"-446.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"249,-438.5 304,-438.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"276.5\" y=\"-423.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"304,-415.5 304,-461.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"359\" y=\"-446.3\">(None, 112, 128)</text>\n",
       "<polyline fill=\"none\" points=\"304,-438.5 414,-438.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"359\" y=\"-423.3\">(None, 112, 128)</text>\n",
       "</g>\n",
       "<!-- 140317137970576&#45;&gt;140317138867152 -->\n",
       "<g class=\"edge\" id=\"edge5\"><title>140317137970576-&gt;140317138867152</title>\n",
       "<path d=\"M254,-498.366C254,-490.152 254,-480.658 254,-471.725\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"257.5,-471.607 254,-461.607 250.5,-471.607 257.5,-471.607\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317137718736 -->\n",
       "<g class=\"node\" id=\"node7\"><title>140317137718736</title>\n",
       "<polygon fill=\"none\" points=\"0,-332.5 0,-378.5 242,-378.5 242,-332.5 0,-332.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"38.5\" y=\"-351.8\">gru1: GRU</text>\n",
       "<polyline fill=\"none\" points=\"77,-332.5 77,-378.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"104.5\" y=\"-363.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"77,-355.5 132,-355.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"104.5\" y=\"-340.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"132,-332.5 132,-378.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"187\" y=\"-363.3\">(None, 112, 128)</text>\n",
       "<polyline fill=\"none\" points=\"132,-355.5 242,-355.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"187\" y=\"-340.3\">(None, 112, 128)</text>\n",
       "</g>\n",
       "<!-- 140317138867152&#45;&gt;140317137718736 -->\n",
       "<g class=\"edge\" id=\"edge6\"><title>140317138867152-&gt;140317137718736</title>\n",
       "<path d=\"M217.657,-415.366C201.676,-405.634 182.748,-394.106 165.896,-383.842\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"167.66,-380.819 157.299,-378.607 164.019,-386.798 167.66,-380.819\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317137718224 -->\n",
       "<g class=\"node\" id=\"node8\"><title>140317137718224</title>\n",
       "<polygon fill=\"none\" points=\"260,-332.5 260,-378.5 516,-378.5 516,-332.5 260,-332.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"305.5\" y=\"-351.8\">gru1_b: GRU</text>\n",
       "<polyline fill=\"none\" points=\"351,-332.5 351,-378.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"378.5\" y=\"-363.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"351,-355.5 406,-355.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"378.5\" y=\"-340.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"406,-332.5 406,-378.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"461\" y=\"-363.3\">(None, 112, 128)</text>\n",
       "<polyline fill=\"none\" points=\"406,-355.5 516,-355.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"461\" y=\"-340.3\">(None, 112, 128)</text>\n",
       "</g>\n",
       "<!-- 140317138867152&#45;&gt;140317137718224 -->\n",
       "<g class=\"edge\" id=\"edge7\"><title>140317138867152-&gt;140317137718224</title>\n",
       "<path d=\"M290.616,-415.366C306.717,-405.634 325.788,-394.106 342.767,-383.842\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"344.681,-386.775 351.428,-378.607 341.06,-380.785 344.681,-386.775\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317136785744 -->\n",
       "<g class=\"node\" id=\"node9\"><title>140317136785744</title>\n",
       "<polygon fill=\"none\" points=\"76,-249.5 76,-295.5 432,-295.5 432,-249.5 76,-249.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"116\" y=\"-268.8\">add_1: Add</text>\n",
       "<polyline fill=\"none\" points=\"156,-249.5 156,-295.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"183.5\" y=\"-280.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"156,-272.5 211,-272.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"183.5\" y=\"-257.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"211,-249.5 211,-295.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"321.5\" y=\"-280.3\">[(None, 112, 128), (None, 112, 128)]</text>\n",
       "<polyline fill=\"none\" points=\"211,-272.5 432,-272.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"321.5\" y=\"-257.3\">(None, 112, 128)</text>\n",
       "</g>\n",
       "<!-- 140317137718736&#45;&gt;140317136785744 -->\n",
       "<g class=\"edge\" id=\"edge8\"><title>140317137718736-&gt;140317136785744</title>\n",
       "<path d=\"M157.343,-332.366C173.324,-322.634 192.252,-311.106 209.104,-300.842\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"210.981,-303.798 217.701,-295.607 207.34,-297.819 210.981,-303.798\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317137718224&#45;&gt;140317136785744 -->\n",
       "<g class=\"edge\" id=\"edge9\"><title>140317137718224-&gt;140317136785744</title>\n",
       "<path d=\"M351.384,-332.366C335.283,-322.634 316.212,-311.106 299.233,-300.842\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"300.94,-297.785 290.572,-295.607 297.319,-303.775 300.94,-297.785\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317133771920 -->\n",
       "<g class=\"node\" id=\"node10\"><title>140317133771920</title>\n",
       "<polygon fill=\"none\" points=\"0,-166.5 0,-212.5 242,-212.5 242,-166.5 0,-166.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"38.5\" y=\"-185.8\">gru2: GRU</text>\n",
       "<polyline fill=\"none\" points=\"77,-166.5 77,-212.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"104.5\" y=\"-197.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"77,-189.5 132,-189.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"104.5\" y=\"-174.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"132,-166.5 132,-212.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"187\" y=\"-197.3\">(None, 112, 128)</text>\n",
       "<polyline fill=\"none\" points=\"132,-189.5 242,-189.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"187\" y=\"-174.3\">(None, 112, 128)</text>\n",
       "</g>\n",
       "<!-- 140317136785744&#45;&gt;140317133771920 -->\n",
       "<g class=\"edge\" id=\"edge10\"><title>140317136785744-&gt;140317133771920</title>\n",
       "<path d=\"M217.657,-249.366C201.676,-239.634 182.748,-228.106 165.896,-217.842\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"167.66,-214.819 157.299,-212.607 164.019,-220.798 167.66,-214.819\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317134672912 -->\n",
       "<g class=\"node\" id=\"node11\"><title>140317134672912</title>\n",
       "<polygon fill=\"none\" points=\"260,-166.5 260,-212.5 516,-212.5 516,-166.5 260,-166.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"305.5\" y=\"-185.8\">gru2_b: GRU</text>\n",
       "<polyline fill=\"none\" points=\"351,-166.5 351,-212.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"378.5\" y=\"-197.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"351,-189.5 406,-189.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"378.5\" y=\"-174.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"406,-166.5 406,-212.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"461\" y=\"-197.3\">(None, 112, 128)</text>\n",
       "<polyline fill=\"none\" points=\"406,-189.5 516,-189.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"461\" y=\"-174.3\">(None, 112, 128)</text>\n",
       "</g>\n",
       "<!-- 140317136785744&#45;&gt;140317134672912 -->\n",
       "<g class=\"edge\" id=\"edge11\"><title>140317136785744-&gt;140317134672912</title>\n",
       "<path d=\"M290.616,-249.366C306.717,-239.634 325.788,-228.106 342.767,-217.842\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"344.681,-220.775 351.428,-212.607 341.06,-214.785 344.681,-220.775\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317132821648 -->\n",
       "<g class=\"node\" id=\"node12\"><title>140317132821648</title>\n",
       "<polygon fill=\"none\" points=\"32,-83.5 32,-129.5 476,-129.5 476,-83.5 32,-83.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"116\" y=\"-102.8\">concatenate_1: Concatenate</text>\n",
       "<polyline fill=\"none\" points=\"200,-83.5 200,-129.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"227.5\" y=\"-114.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"200,-106.5 255,-106.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"227.5\" y=\"-91.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"255,-83.5 255,-129.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"365.5\" y=\"-114.3\">[(None, 112, 128), (None, 112, 128)]</text>\n",
       "<polyline fill=\"none\" points=\"255,-106.5 476,-106.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"365.5\" y=\"-91.3\">(None, 112, 256)</text>\n",
       "</g>\n",
       "<!-- 140317133771920&#45;&gt;140317132821648 -->\n",
       "<g class=\"edge\" id=\"edge12\"><title>140317133771920-&gt;140317132821648</title>\n",
       "<path d=\"M157.343,-166.366C173.324,-156.634 192.252,-145.106 209.104,-134.842\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"210.981,-137.798 217.701,-129.607 207.34,-131.819 210.981,-137.798\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317134672912&#45;&gt;140317132821648 -->\n",
       "<g class=\"edge\" id=\"edge13\"><title>140317134672912-&gt;140317132821648</title>\n",
       "<path d=\"M351.384,-166.366C335.283,-156.634 316.212,-145.106 299.233,-134.842\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"300.94,-131.785 290.572,-129.607 297.319,-137.775 300.94,-131.785\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- 140317031581776 -->\n",
       "<g class=\"node\" id=\"node13\"><title>140317031581776</title>\n",
       "<polygon fill=\"none\" points=\"120.5,-0.5 120.5,-46.5 387.5,-46.5 387.5,-0.5 120.5,-0.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"171.5\" y=\"-19.8\">dense_2: Dense</text>\n",
       "<polyline fill=\"none\" points=\"222.5,-0.5 222.5,-46.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"250\" y=\"-31.3\">input:</text>\n",
       "<polyline fill=\"none\" points=\"222.5,-23.5 277.5,-23.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"250\" y=\"-8.3\">output:</text>\n",
       "<polyline fill=\"none\" points=\"277.5,-0.5 277.5,-46.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"332.5\" y=\"-31.3\">(None, 112, 256)</text>\n",
       "<polyline fill=\"none\" points=\"277.5,-23.5 387.5,-23.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"332.5\" y=\"-8.3\">(None, 112, 45)</text>\n",
       "</g>\n",
       "<!-- 140317132821648&#45;&gt;140317031581776 -->\n",
       "<g class=\"edge\" id=\"edge14\"><title>140317132821648-&gt;140317031581776</title>\n",
       "<path d=\"M254,-83.3664C254,-75.1516 254,-65.6579 254,-56.7252\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"257.5,-56.6068 254,-46.6068 250.5,-56.6069 257.5,-56.6068\" stroke=\"black\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>"
      ],
      "text/plain": [
       "<IPython.core.display.SVG object>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "SVG(model_to_dot(base_model, show_shapes=True).create(prog='dot', format='svg'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 载入训练集做验证集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 10240/10240 [00:10<00:00, 1007.26it/s]\n"
     ]
    }
   ],
   "source": [
    "n1 = 350*256\n",
    "n2 = 390*256\n",
    "\n",
    "X = np.zeros((n2-n1, width, height, channels), dtype=np.uint8)\n",
    "y = np.zeros((n2-n1, n_len), dtype=np.uint8)\n",
    "\n",
    "for i in tqdm(range(n1, n2)):\n",
    "    img = cv2.imread('crop_split2/%d.png'%i).transpose(1, 0, 2)\n",
    "    a, b, _ = img.shape\n",
    "    X[i-n1, :a, :b] = img\n",
    "    \n",
    "    label = df[0][i].decode('utf-8')\n",
    "    y[i-n1,:len(label)] = [characters.find(x) for x in label]\n",
    "    y[i-n1,len(label):] = n_class-1\n",
    "\n",
    "X_val = [X, y, np.ones(n2-n1)*rnn_length, labels_len[n1:n2]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 生成器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 89600/89600 [01:34<00:00, 944.04it/s] \n"
     ]
    }
   ],
   "source": [
    "from collections import defaultdict\n",
    "\n",
    "cn_imgs = defaultdict(list)\n",
    "cn_labels = defaultdict(list)\n",
    "ss_imgs = []\n",
    "ss_labels = []\n",
    "\n",
    "for i in tqdm(range(n1)):\n",
    "    ss = df[0][i].decode('utf-8').split(';')\n",
    "    m = len(ss)-1\n",
    "    ss_labels.append(ss[-1])\n",
    "    ss_imgs.append(cv2.imread('crop_split2/%d_%d.png'%(i, 0)).transpose(1, 0, 2))\n",
    "    for j in range(m):\n",
    "        cn_labels[ss[j][0]].append(ss[j])\n",
    "        cn_imgs[ss[j][0]].append(cv2.imread('crop_split2/%d_%d.png'%(i, m-j)).transpose(1, 0, 2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from keras.utils import Sequence\n",
    "\n",
    "class SGen(Sequence):\n",
    "    def __init__(self, batch_size):\n",
    "        self.batch_size = batch_size\n",
    "        self.X_gen = np.zeros((batch_size, width, height, 3), dtype=np.uint8)\n",
    "        self.y_gen = np.zeros((batch_size, n_len), dtype=np.uint8)\n",
    "        self.input_length = np.ones(batch_size)*rnn_length\n",
    "        self.label_length = np.ones(batch_size)*38\n",
    "    \n",
    "    def __len__(self):\n",
    "        return 350*256 // self.batch_size\n",
    "    \n",
    "    def __getitem__(self, idx):\n",
    "        self.X_gen[:] = 0\n",
    "        for i in range(self.batch_size):\n",
    "            try:\n",
    "                random_index = random.randint(0, n1-1)\n",
    "                cls = []\n",
    "                ss = ss_labels[random_index]\n",
    "                cs = re.findall(ur'[\\u4e00-\\u9fff]', df[0][random_index].decode('utf-8').split(';')[-1])\n",
    "                random.shuffle(cs)\n",
    "                x = 0\n",
    "                for c in cs:\n",
    "                    random_index2 = random.randint(0, len(cn_labels[c])-1)\n",
    "                    cls.append(cn_labels[c][random_index2])\n",
    "                    img = cn_imgs[c][random_index2]\n",
    "                    w, h, _ = img.shape\n",
    "                    self.X_gen[i, x:x+w, :h] = img\n",
    "                    x += w+2\n",
    "                img = ss_imgs[random_index]\n",
    "                w, h, _ = img.shape\n",
    "                self.X_gen[i, x:x+w, :h] = img\n",
    "                cls.append(ss)\n",
    "\n",
    "                random_str = u';'.join(cls)\n",
    "                self.y_gen[i,:len(random_str)] = [characters.find(x) for x in random_str]\n",
    "                self.y_gen[i,len(random_str):] = n_class-1\n",
    "                self.label_length[i] = len(random_str)\n",
    "            except:\n",
    "                pass\n",
    "        \n",
    "        return [self.X_gen, self.y_gen, self.input_length, self.label_length], np.ones(self.batch_size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 可视化生成器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "110.0\n",
      "39.0\n",
      "铁=33940;河=95141;85882*(河/76020-37023)-铁\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gen = SGen(1)\n",
    "(X_vis, y_vis, input_length_vis, label_length_vis), _ = gen[0]\n",
    "print input_length_vis[0]\n",
    "print label_length_vis[0]\n",
    "print decode(y_vis[0])\n",
    "disp2(X_vis[0].transpose((1, 0, 2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def evaluate():\n",
    "    global out\n",
    "    y_pred = base_model2.predict(X, batch_size=128, verbose=1)\n",
    "    out = K.get_value(K.ctc_decode(y_pred[:,2:], input_length=np.ones(y_pred.shape[0])*rnn_length)[0][0])[:, :n_len]\n",
    "    out[out == -1] = n_class-1\n",
    "    score = (out == y[:,:out.shape[-1]]).all(axis=-1).mean()\n",
    "    base_model.save('model_%s_%.6f.h5' % (DESCRIPTION, score))\n",
    "    return score\n",
    "\n",
    "def train(epochs=10, optimizer=None, batch_size=128, callbacks=None):\n",
    "    if optimizer:\n",
    "        model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer=optimizer)\n",
    "    model.fit_generator(SGen(batch_size), steps_per_epoch=390, \n",
    "                        workers=6, use_multiprocessing=True,\n",
    "                        validation_data=(X_val, np.ones(n2-n1)), epochs=epochs, callbacks=callbacks)\n",
    "    print evaluate()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 采用每次训练最好的模型\n",
    "\n",
    "http://keras-cn.readthedocs.io/en/latest/other/callbacks/#modelcheckpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from keras.callbacks import *\n",
    "\n",
    "mc = ModelCheckpoint(MODEL_NAME, save_best_only=True)\n",
    "cl = CSVLogger('model_%s.csv' % DESCRIPTION, append=True)\n",
    "\n",
    "class Evaluator(Callback):\n",
    "    def __init__(self):\n",
    "        self.accs = []\n",
    "    \n",
    "    def on_epoch_end(self, epoch, logs=None):\n",
    "        acc = evaluate()*100\n",
    "        self.accs.append(acc)\n",
    "        print 'acc: %f%%'%acc\n",
    "\n",
    "ev = Evaluator()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/50\n",
      "390/390 [==============================] - 520s - loss: 67.3760 - val_loss: 7.0791\n",
      "Epoch 2/50\n",
      "390/390 [==============================] - 523s - loss: 2.0970 - val_loss: 1.6675\n",
      "Epoch 3/50\n",
      "390/390 [==============================] - 522s - loss: 0.9834 - val_loss: 1.4168\n",
      "Epoch 4/50\n",
      "390/390 [==============================] - 521s - loss: 0.8086 - val_loss: 3.1642\n",
      "Epoch 5/50\n",
      "390/390 [==============================] - 523s - loss: 0.7597 - val_loss: 1.0960\n",
      "Epoch 6/50\n",
      "390/390 [==============================] - 523s - loss: 0.7076 - val_loss: 1.0054\n",
      "Epoch 7/50\n",
      "390/390 [==============================] - 523s - loss: 0.6665 - val_loss: 0.9307\n",
      "Epoch 8/50\n",
      "390/390 [==============================] - 522s - loss: 0.6603 - val_loss: 0.9200\n",
      "Epoch 9/50\n",
      "390/390 [==============================] - 524s - loss: 0.6206 - val_loss: 1.1339\n",
      "Epoch 10/50\n",
      "390/390 [==============================] - 523s - loss: 0.6250 - val_loss: 0.9328\n",
      "Epoch 11/50\n",
      "390/390 [==============================] - 525s - loss: 0.6113 - val_loss: 0.6485\n",
      "Epoch 12/50\n",
      "390/390 [==============================] - 525s - loss: 0.5880 - val_loss: 0.6735\n",
      "Epoch 13/50\n",
      "390/390 [==============================] - 519s - loss: 0.5686 - val_loss: 1.3073\n",
      "Epoch 14/50\n",
      "390/390 [==============================] - 523s - loss: 0.5622 - val_loss: 0.7076\n",
      "Epoch 15/50\n",
      "390/390 [==============================] - 522s - loss: 0.5543 - val_loss: 0.5705\n",
      "Epoch 16/50\n",
      "390/390 [==============================] - 524s - loss: 0.5460 - val_loss: 0.8837\n",
      "Epoch 17/50\n",
      "390/390 [==============================] - 523s - loss: 0.5379 - val_loss: 0.6000\n",
      "Epoch 18/50\n",
      "390/390 [==============================] - 519s - loss: 0.5478 - val_loss: 3.0010\n",
      "Epoch 19/50\n",
      "390/390 [==============================] - 523s - loss: 0.5444 - val_loss: 0.5377\n",
      "Epoch 20/50\n",
      "390/390 [==============================] - 522s - loss: 0.5015 - val_loss: 0.5837\n",
      "Epoch 21/50\n",
      "390/390 [==============================] - 519s - loss: 0.5039 - val_loss: 14.4374\n",
      "Epoch 22/50\n",
      "390/390 [==============================] - 517s - loss: 0.5125 - val_loss: 0.6311\n",
      "Epoch 23/50\n",
      "390/390 [==============================] - 516s - loss: 0.4959 - val_loss: 0.8603\n",
      "Epoch 24/50\n",
      "390/390 [==============================] - 517s - loss: 0.4674 - val_loss: 0.4551\n",
      "Epoch 25/50\n",
      "390/390 [==============================] - 515s - loss: 0.4582 - val_loss: 0.5902\n",
      "Epoch 26/50\n",
      "390/390 [==============================] - 516s - loss: 0.4443 - val_loss: 0.4657\n",
      "Epoch 27/50\n",
      "390/390 [==============================] - 515s - loss: 0.5454 - val_loss: 0.7502\n",
      "Epoch 28/50\n",
      "390/390 [==============================] - 516s - loss: 0.5120 - val_loss: 1.4974\n",
      "Epoch 29/50\n",
      "390/390 [==============================] - 514s - loss: 0.4681 - val_loss: 0.6189\n",
      "Epoch 30/50\n",
      "390/390 [==============================] - 514s - loss: 0.4730 - val_loss: 0.4317\n",
      "Epoch 31/50\n",
      "390/390 [==============================] - 515s - loss: 0.4136 - val_loss: 0.5464\n",
      "Epoch 32/50\n",
      "390/390 [==============================] - 516s - loss: 0.4205 - val_loss: 1.2078\n",
      "Epoch 33/50\n",
      "390/390 [==============================] - 515s - loss: 0.3985 - val_loss: 0.5356\n",
      "Epoch 34/50\n",
      "390/390 [==============================] - 515s - loss: 0.4152 - val_loss: 0.3879\n",
      "Epoch 35/50\n",
      "390/390 [==============================] - 517s - loss: 0.4117 - val_loss: 0.7477\n",
      "Epoch 36/50\n",
      "390/390 [==============================] - 516s - loss: 0.3948 - val_loss: 0.4813\n",
      "Epoch 37/50\n",
      "390/390 [==============================] - 518s - loss: 0.4062 - val_loss: 1.2658\n",
      "Epoch 38/50\n",
      "390/390 [==============================] - 521s - loss: 0.3745 - val_loss: 0.7688\n",
      "Epoch 39/50\n",
      "390/390 [==============================] - 520s - loss: 0.3546 - val_loss: 0.4661\n",
      "Epoch 40/50\n",
      "390/390 [==============================] - 521s - loss: 0.3819 - val_loss: 0.6336\n",
      "Epoch 41/50\n",
      "390/390 [==============================] - 519s - loss: 0.3679 - val_loss: 0.5752\n",
      "Epoch 42/50\n",
      "390/390 [==============================] - 521s - loss: 0.3490 - val_loss: 0.5478\n",
      "Epoch 43/50\n",
      "390/390 [==============================] - 522s - loss: 0.3500 - val_loss: 0.4112\n",
      "Epoch 44/50\n",
      "390/390 [==============================] - 518s - loss: 0.3489 - val_loss: 9.1006\n",
      "Epoch 45/50\n",
      "390/390 [==============================] - 513s - loss: 0.3999 - val_loss: 5.3200\n",
      "Epoch 46/50\n",
      "390/390 [==============================] - 513s - loss: 0.3543 - val_loss: 0.5263\n",
      "Epoch 47/50\n",
      "390/390 [==============================] - 512s - loss: 0.3701 - val_loss: 0.5150\n",
      "Epoch 48/50\n",
      "390/390 [==============================] - 512s - loss: 0.3478 - val_loss: 0.3652\n",
      "Epoch 49/50\n",
      "390/390 [==============================] - 514s - loss: 0.3339 - val_loss: 0.3858\n",
      "Epoch 50/50\n",
      "390/390 [==============================] - 512s - loss: 0.3325 - val_loss: 0.3689\n",
      "10240/10240 [==============================] - 35s    \n",
      "0.97763671875\n"
     ]
    }
   ],
   "source": [
    "opt = Adam()\n",
    "train(epochs=50, optimizer=opt, callbacks=[mc, cl])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10240/10240 [==============================] - 33s    \n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.97910156250000002"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.load_weights(MODEL_NAME)\n",
    "evaluate()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/50\n",
      "390/390 [==============================] - 516s - loss: 0.3033 - val_loss: 0.2976\n",
      "Epoch 2/50\n",
      "390/390 [==============================] - 514s - loss: 0.2811 - val_loss: 0.2929\n",
      "Epoch 3/50\n",
      "390/390 [==============================] - 514s - loss: 0.2752 - val_loss: 0.2796\n",
      "Epoch 4/50\n",
      "390/390 [==============================] - 515s - loss: 0.2582 - val_loss: 0.2643\n",
      "Epoch 5/50\n",
      "390/390 [==============================] - 518s - loss: 0.2483 - val_loss: 0.2565\n",
      "Epoch 6/50\n",
      "390/390 [==============================] - 516s - loss: 0.2396 - val_loss: 0.2459\n",
      "Epoch 7/50\n",
      "390/390 [==============================] - 515s - loss: 0.2294 - val_loss: 0.2381\n",
      "Epoch 8/50\n",
      "390/390 [==============================] - 515s - loss: 0.2208 - val_loss: 0.2295\n",
      "Epoch 9/50\n",
      "390/390 [==============================] - 514s - loss: 0.2137 - val_loss: 0.2241\n",
      "Epoch 10/50\n",
      "390/390 [==============================] - 514s - loss: 0.2059 - val_loss: 0.2143\n",
      "Epoch 11/50\n",
      "390/390 [==============================] - 512s - loss: 0.1985 - val_loss: 0.2095\n",
      "Epoch 12/50\n",
      "390/390 [==============================] - 515s - loss: 0.1933 - val_loss: 0.2148\n",
      "Epoch 13/50\n",
      "390/390 [==============================] - 516s - loss: 0.1866 - val_loss: 0.1958\n",
      "Epoch 14/50\n",
      "390/390 [==============================] - 516s - loss: 0.1817 - val_loss: 0.2011\n",
      "Epoch 15/50\n",
      "390/390 [==============================] - 516s - loss: 0.1782 - val_loss: 0.1858\n",
      "Epoch 16/50\n",
      "390/390 [==============================] - 514s - loss: 0.1807 - val_loss: 0.1884\n",
      "Epoch 17/50\n",
      "390/390 [==============================] - 516s - loss: 0.1692 - val_loss: 0.1802\n",
      "Epoch 18/50\n",
      "390/390 [==============================] - 516s - loss: 0.1641 - val_loss: 0.1712\n",
      "Epoch 19/50\n",
      "390/390 [==============================] - 517s - loss: 0.1591 - val_loss: 0.1772\n",
      "Epoch 20/50\n",
      "390/390 [==============================] - 515s - loss: 0.1645 - val_loss: 0.1757\n",
      "Epoch 21/50\n",
      "390/390 [==============================] - 515s - loss: 0.1575 - val_loss: 0.1661\n",
      "Epoch 22/50\n",
      "390/390 [==============================] - 517s - loss: 0.1496 - val_loss: 0.1614\n",
      "Epoch 23/50\n",
      "390/390 [==============================] - 515s - loss: 0.1473 - val_loss: 0.1616\n",
      "Epoch 24/50\n",
      "390/390 [==============================] - 517s - loss: 0.1516 - val_loss: 0.1551\n",
      "Epoch 25/50\n",
      "390/390 [==============================] - 517s - loss: 0.1491 - val_loss: 0.1569\n",
      "Epoch 26/50\n",
      "390/390 [==============================] - 518s - loss: 0.1405 - val_loss: 0.1568\n",
      "Epoch 27/50\n",
      "390/390 [==============================] - 516s - loss: 0.1440 - val_loss: 0.1557\n",
      "Epoch 28/50\n",
      "390/390 [==============================] - 514s - loss: 0.1363 - val_loss: 0.1584\n",
      "Epoch 29/50\n",
      "390/390 [==============================] - 513s - loss: 0.1329 - val_loss: 0.1456\n",
      "Epoch 30/50\n",
      "390/390 [==============================] - 511s - loss: 0.1306 - val_loss: 0.1438\n",
      "Epoch 31/50\n",
      "390/390 [==============================] - 512s - loss: 0.1281 - val_loss: 0.1426\n",
      "Epoch 32/50\n",
      "390/390 [==============================] - 512s - loss: 0.1271 - val_loss: 0.1496\n",
      "Epoch 33/50\n",
      "390/390 [==============================] - 512s - loss: 0.1257 - val_loss: 0.1388\n",
      "Epoch 34/50\n",
      "390/390 [==============================] - 513s - loss: 0.1234 - val_loss: 0.1337\n",
      "Epoch 35/50\n",
      "390/390 [==============================] - 514s - loss: 0.1308 - val_loss: 0.1423\n",
      "Epoch 36/50\n",
      "390/390 [==============================] - 512s - loss: 0.1248 - val_loss: 0.1359\n",
      "Epoch 37/50\n",
      "390/390 [==============================] - 514s - loss: 0.1185 - val_loss: 0.1321\n",
      "Epoch 38/50\n",
      "390/390 [==============================] - 514s - loss: 0.1169 - val_loss: 0.1292\n",
      "Epoch 39/50\n",
      "390/390 [==============================] - 517s - loss: 0.1158 - val_loss: 0.1322\n",
      "Epoch 40/50\n",
      "390/390 [==============================] - 517s - loss: 0.1202 - val_loss: 0.1313\n",
      "Epoch 41/50\n",
      "390/390 [==============================] - 519s - loss: 0.1133 - val_loss: 0.1244\n",
      "Epoch 42/50\n",
      "390/390 [==============================] - 514s - loss: 0.1120 - val_loss: 0.1309\n",
      "Epoch 43/50\n",
      "390/390 [==============================] - 516s - loss: 0.1130 - val_loss: 0.1247\n",
      "Epoch 44/50\n",
      "390/390 [==============================] - 519s - loss: 0.1092 - val_loss: 0.1218\n",
      "Epoch 45/50\n",
      "390/390 [==============================] - 517s - loss: 0.1069 - val_loss: 0.1187\n",
      "Epoch 46/50\n",
      "390/390 [==============================] - 514s - loss: 0.1071 - val_loss: 0.1158\n",
      "Epoch 47/50\n",
      "390/390 [==============================] - 512s - loss: 0.1068 - val_loss: 0.1222\n",
      "Epoch 48/50\n",
      "390/390 [==============================] - 512s - loss: 0.1075 - val_loss: 0.1249\n",
      "Epoch 49/50\n",
      "390/390 [==============================] - 513s - loss: 0.1043 - val_loss: 0.1145\n",
      "Epoch 50/50\n",
      "390/390 [==============================] - 511s - loss: 0.1017 - val_loss: 0.1171\n",
      "10240/10240 [==============================] - 33s    \n",
      "0.9966796875\n"
     ]
    }
   ],
   "source": [
    "opt = Adam(1e-4)\n",
    "train(epochs=50, optimizer=opt, callbacks=[mc, cl])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10240/10240 [==============================] - 34s    \n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.99726562500000004"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.load_weights(MODEL_NAME)\n",
    "evaluate()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/20\n",
      "10240/10240 [==============================] - 33s    \n",
      "acc: 99.736328%\n",
      "390/390 [==============================] - 480s - loss: 0.1023 - val_loss: 0.1125\n",
      "Epoch 2/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.746094%\n",
      "390/390 [==============================] - 480s - loss: 0.1016 - val_loss: 0.1116\n",
      "Epoch 3/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.736328%\n",
      "390/390 [==============================] - 481s - loss: 0.1014 - val_loss: 0.1110\n",
      "Epoch 4/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.755859%\n",
      "390/390 [==============================] - 482s - loss: 0.1010 - val_loss: 0.1106\n",
      "Epoch 5/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.726562%\n",
      "390/390 [==============================] - 484s - loss: 0.1211 - val_loss: 0.1110\n",
      "Epoch 6/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.736328%\n",
      "390/390 [==============================] - 488s - loss: 0.1006 - val_loss: 0.1108\n",
      "Epoch 7/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.716797%\n",
      "390/390 [==============================] - 489s - loss: 0.1001 - val_loss: 0.1110\n",
      "Epoch 8/20\n",
      "10240/10240 [==============================] - 37s    \n",
      "acc: 99.746094%\n",
      "390/390 [==============================] - 498s - loss: 0.0998 - val_loss: 0.1102\n",
      "Epoch 9/20\n",
      "10240/10240 [==============================] - 39s    \n",
      "acc: 99.736328%\n",
      "390/390 [==============================] - 502s - loss: 0.0996 - val_loss: 0.1097\n",
      "Epoch 10/20\n",
      "10240/10240 [==============================] - 39s    \n",
      "acc: 99.736328%\n",
      "390/390 [==============================] - 508s - loss: 0.0991 - val_loss: 0.1095\n",
      "Epoch 11/20\n",
      "10240/10240 [==============================] - 38s    \n",
      "acc: 99.716797%\n",
      "390/390 [==============================] - 513s - loss: 0.0987 - val_loss: 0.1089\n",
      "Epoch 12/20\n",
      "10240/10240 [==============================] - 41s    \n",
      "acc: 99.726562%\n",
      "390/390 [==============================] - 524s - loss: 0.0982 - val_loss: 0.1089\n",
      "Epoch 13/20\n",
      "10240/10240 [==============================] - 44s    \n",
      "acc: 99.736328%\n",
      "390/390 [==============================] - 529s - loss: 0.0977 - val_loss: 0.1079\n",
      "Epoch 14/20\n",
      "10240/10240 [==============================] - 43s    \n",
      "acc: 99.765625%\n",
      "390/390 [==============================] - 541s - loss: 0.0972 - val_loss: 0.1067\n",
      "Epoch 15/20\n",
      "10240/10240 [==============================] - 43s    \n",
      "acc: 99.726562%\n",
      "390/390 [==============================] - 538s - loss: 0.1046 - val_loss: 0.1071\n",
      "Epoch 16/20\n",
      "10240/10240 [==============================] - 48s    \n",
      "acc: 99.726562%\n",
      "390/390 [==============================] - 553s - loss: 0.0962 - val_loss: 0.1064\n",
      "Epoch 17/20\n",
      "10240/10240 [==============================] - 44s    \n",
      "acc: 99.746094%\n",
      "390/390 [==============================] - 553s - loss: 0.0958 - val_loss: 0.1053\n",
      "Epoch 18/20\n",
      "10240/10240 [==============================] - 43s    \n",
      "acc: 99.765625%\n",
      "390/390 [==============================] - 547s - loss: 0.0952 - val_loss: 0.1046\n",
      "Epoch 19/20\n",
      "196/390 [==============>...............] - ETA: 225s - loss: 0.0948"
     ]
    }
   ],
   "source": [
    "opt = Adam(1e-5)\n",
    "train(epochs=20, optimizer=opt, batch_size=100, callbacks=[mc, cl, ev])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10240/10240 [==============================] - 33s    \n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.99765625000000002"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "evaluate()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "base_model.load_weights('model_346_split2_3_0.997656.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/20\n",
      "10240/10240 [==============================] - 35s    \n",
      "acc: 99.726562%\n",
      "390/390 [==============================] - 416s - loss: 0.0941 - val_loss: 0.1045\n",
      "Epoch 2/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.716797%\n",
      "390/390 [==============================] - 413s - loss: 0.1036 - val_loss: 0.1041\n",
      "Epoch 3/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.716797%\n",
      "390/390 [==============================] - 412s - loss: 0.0931 - val_loss: 0.1037\n",
      "Epoch 4/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.716797%\n",
      "390/390 [==============================] - 413s - loss: 0.0927 - val_loss: 0.1032\n",
      "Epoch 5/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.746094%\n",
      "390/390 [==============================] - 415s - loss: 0.0921 - val_loss: 0.1026\n",
      "Epoch 6/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.755859%\n",
      "390/390 [==============================] - 414s - loss: 0.0916 - val_loss: 0.1020\n",
      "Epoch 7/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.755859%\n",
      "390/390 [==============================] - 413s - loss: 0.1019 - val_loss: 0.1013\n",
      "Epoch 8/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.726562%\n",
      "390/390 [==============================] - 416s - loss: 0.0905 - val_loss: 0.1017\n",
      "Epoch 9/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.746094%\n",
      "390/390 [==============================] - 414s - loss: 0.0902 - val_loss: 0.1010\n",
      "Epoch 10/20\n",
      "10240/10240 [==============================] - 35s    \n",
      "acc: 99.746094%\n",
      "390/390 [==============================] - 413s - loss: 0.0898 - val_loss: 0.1010\n",
      "Epoch 11/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.746094%\n",
      "390/390 [==============================] - 414s - loss: 0.0895 - val_loss: 0.0997\n",
      "Epoch 12/20\n",
      "10240/10240 [==============================] - 35s    \n",
      "acc: 99.775391%\n",
      "390/390 [==============================] - 414s - loss: 0.0891 - val_loss: 0.0995\n",
      "Epoch 13/20\n",
      "10240/10240 [==============================] - 35s    \n",
      "acc: 99.765625%\n",
      "390/390 [==============================] - 415s - loss: 0.0888 - val_loss: 0.0990\n",
      "Epoch 14/20\n",
      "10240/10240 [==============================] - 35s    \n",
      "acc: 99.775391%\n",
      "390/390 [==============================] - 414s - loss: 0.0885 - val_loss: 0.0995\n",
      "Epoch 15/20\n",
      "10240/10240 [==============================] - 35s    \n",
      "acc: 99.746094%\n",
      "390/390 [==============================] - 413s - loss: 0.0880 - val_loss: 0.0989\n",
      "Epoch 16/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.775391%\n",
      "390/390 [==============================] - 413s - loss: 0.1026 - val_loss: 0.0993\n",
      "Epoch 17/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.726562%\n",
      "390/390 [==============================] - 413s - loss: 0.0874 - val_loss: 0.0993\n",
      "Epoch 18/20\n",
      "10240/10240 [==============================] - 34s    \n",
      "acc: 99.736328%\n",
      "390/390 [==============================] - 413s - loss: 0.0871 - val_loss: 0.0991\n",
      "Epoch 19/20\n",
      "10240/10240 [==============================] - 35s    \n",
      "acc: 99.746094%\n",
      "390/390 [==============================] - 415s - loss: 0.0868 - val_loss: 0.0994\n",
      "Epoch 20/20\n",
      "10240/10240 [==============================] - 35s    \n",
      "acc: 99.755859%\n",
      "390/390 [==============================] - 419s - loss: 0.0864 - val_loss: 0.0976\n",
      "10240/10240 [==============================] - 35s    \n",
      "0.99755859375\n"
     ]
    }
   ],
   "source": [
    "opt = Adam(1e-5)\n",
    "train(epochs=20, optimizer=opt, batch_size=64, callbacks=[mc, cl, ev])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "base_model.load_weights('model_346_split2_3_0.997754.h5')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 总体准确率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10240/10240 [==============================] - 34s    \n"
     ]
    }
   ],
   "source": [
    "y_pred = base_model2.predict(X, batch_size=128, verbose=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.99775390625000004"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "out = K.get_value(K.ctc_decode(y_pred[:,2:], input_length=np.ones(y_pred.shape[0])*rnn_length)[0][0])[:, :n_len]\n",
    "out[out == -1] = n_class-1\n",
    "score = (out == y[:,:out.shape[-1]]).all(axis=-1).mean()\n",
    "score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "sp = map(decode, out)\n",
    "st = map(decode, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 赋值式准确率与表达式准确率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.99990234374999998"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.array([a.split(';')[:-1] == b.split(';')[:-1] for a, b in zip(sp, st)]).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.99785156249999996"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.array([a.split(';')[-1] == b.split(';')[-1] for a, b in zip(sp, st)]).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
